﻿using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;

namespace FlashPay.DAO.Impl
{
    using FlashPay.DAO.Interface;
    using FlashPay.EF;
    using FlashPay.EF.Models;
    using FlashPay.Entity;
    using FlashPay.Entity.Enum;
    using FlashPay.Entity.Parameter;
    using FlashPay.Entity.Request.Payment;
    using FlashPay.Entity.Response.Payment;
    using FlashPay.Entity.Response.Sys;
    using Microsoft.AspNetCore.Http;
    using Microsoft.EntityFrameworkCore;
    using System.Data;

    /// <summary>
    /// 实际付款数据接口实现			
    /// </summary>
    /// <remarks>2018-07-06 immi 创建</remarks>
    public class RecordRealDaoImpl : RecordRealDao
    {
        #region 注入
        /// <summary>
        /// EF上下文
        /// </summary>
        private FlashPayContext _context { set; get; }

        /// <summary>
        /// 日志模型
        /// </summary>
        private readonly LogRecord _logRecord;

        /// <summary>
        /// 日志模型
        /// </summary>
        private readonly LogDao _logDao;

        /// <summary>
        /// 锁对象
        /// </summary>
        private static object _lock = new object();

        /// <summary>
        /// 注入
        /// </summary>
        /// <param name="context"></param>
        public RecordRealDaoImpl(FlashPayContext context, LogRecord logRecord, LogDao logDao)
        {
            _context = context;
            _logRecord = logRecord;
            _logDao = logDao;
        }

        public void Dispose()
        {
            if (_context != null)
            {
                _context.Dispose();
            }
        }
        #endregion

        /// <summary>
        /// 获取订单月份
        /// </summary>
        /// <param name="month"></param>
        /// <returns></returns>
        private string GetOrderMonth(long orderNo)
        {
            return orderNo.ToString().Substring(4, 2);
        }

        /// <summary>
        /// 根据编号获取余额变化记录
        /// </summary>
        /// <param name="orderNo">编号</param>
        /// <returns>Company</returns>
        public RecordReal Get(long orderNo)
        {
            var tableName = $"RecordReal_{DateTime.Now.ToString("MM")}";

            var month = GetOrderMonth(orderNo);

            if (month != DateTime.Now.ToString("MM"))
            {
                tableName = $"RecordReal_{month}";
            }

            var sql = $"SELECT * FROM {tableName} WHERE OrderNo={orderNo}";

            var recordReal = _context.RecordReal
                .FromSql(sql)
                .AsNoTracking()
                .SingleOrDefault();

            return recordReal;
        }

        /// <summary>
        /// 获取付款记录
        /// </summary>
        /// <param name="orderNo">编号</param>
        /// <returns>Company</returns>
        public PaymentRecord GetPaymentRecord(long orderNo)
        {
            var tableName = $"PaymentRecord_{DateTime.Now.ToString("MM")}";

            var month = GetOrderMonth(orderNo);

            if (month != DateTime.Now.ToString("MM"))
            {
                tableName = $"PaymentRecord_{month}";
            }

            var sql = $"SELECT * FROM {tableName} WHERE OrderNo={orderNo}";

            var paymentRecord = _context.PaymentRecord
                .FromSql(sql)
                .AsNoTracking()
                .SingleOrDefault();

            return paymentRecord;
        }

        /// <summary>
        /// 根据编号获取余额变化记录
        /// </summary>
        /// <param name="orderNo">编号</param>
        /// <returns>Company</returns>
        public RecordRealGetResponse GetByOrderNo(long orderNo)
        {
            var recordReal = this.Get(orderNo);
            if (recordReal != null)
            {
                //获取银行卡
                var bankCard = _context.BankCard.FirstOrDefault(p => p.Bcid == recordReal.CardBcid);
                if (bankCard == null)
                {
                    throw new Exception("实际存款记录的银行卡不存在！");
                }

                //获取公司
                var company = _context.Company.FirstOrDefault(p => p.CompanyId == recordReal.CompanyId);
                if (bankCard == null)
                {
                    throw new Exception("实际存款记录的公司不存在！");
                }

                var recordRealResponse = new RecordRealGetResponse();
                recordRealResponse.OrderNo = recordReal.OrderNo.ToString();
                recordRealResponse.ClientOrderNo = recordReal.ClientOrderNo;
                recordRealResponse.AfterBalance = recordReal.AfterBalance;
                recordRealResponse.CompanyId = recordReal.CompanyId;
                recordRealResponse.CompanyName = company.CompanyName;

                recordRealResponse.Remark = recordReal.Remark;
                recordRealResponse.RecordType = recordReal.RecordType;
                recordRealResponse.CreateDate = recordReal.CreateDate.ToString("yyyy-MM-dd HH:mm:ss");
                recordRealResponse.CreateDbdate = recordReal.CreateDbdate.ToString("yyyy-MM-dd HH:mm:ss");
                recordRealResponse.OperatingDate = recordReal.OperatingDate.ToString("yyyy-MM-dd HH:mm:ss");
                recordRealResponse.CardBcid = recordReal.CardBcid;
                recordRealResponse.BankName = bankCard.BankName;
                recordRealResponse.BankCardName = bankCard.CardName;
                recordRealResponse.BankCardNumber = bankCard.CardNumber;
                recordRealResponse.Amount = recordReal.Amount.ToString("#0.00");
                recordRealResponse.ClientBankName = recordReal.ClientBankName;
                recordRealResponse.ClientAccountName = recordReal.ClientAccountName;
                recordRealResponse.ClientCardNumber = recordReal.ClientCardNumber;
                recordRealResponse.BankSerialNo = recordReal.BankSerialNo;
                recordRealResponse.VmClientId = recordReal.VmClientId;
                recordRealResponse.MatchOrderNo = recordReal.MatchOrderNo;

                var configs = _context.SysConfig.Where(p => p.ConfigCode == "Transtype" && p.CompanyId == 2).ToList();
                if (configs != null && configs.Any()) {

                    var sysConfigResponses = new List<SysConfigResponse>();
                    configs.ForEach(item => {
                        sysConfigResponses.Add(new SysConfigResponse() {
                            ConfigId = item.ConfigId,
                            ConfigValue = item.ConfigValue,
                            ConfigContent = item.ConfigContent
                        });
                    });
                    recordRealResponse.SysConfigResponse = sysConfigResponses;
                }
                return recordRealResponse;
            }
            else {
                return null;
            }
        }

        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="userInfo">新增对象</param>
        /// <returns></returns>
        public long Add(RecordReal model)
        {
            _context.RecordReal.Add(model);
            _context.SaveChanges();
            return model.OrderNo;
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="CardMerchant">修改对象</param>
        /// <returns></returns>
        public bool Update(RecordReal model)
        {
            bool result = false;

            var adjustBalance = _context.RecordReal.Find(model.OrderNo);
            if (adjustBalance != null)
            {
                _context.SaveChanges();
                result = true;
            }
            return result;
        }

        /// <summary>
        /// 更新状态
        /// </summary>
        /// <param name="id">系统编号</param>
        /// <param name="status">状态</param>
        /// <returns></returns>
        public bool UpdateStatus(int id, SByte status)
        {
            var model = _context.RecordReal.Where(p => p.OrderNo.Equals(id)).FirstOrDefault();
            if (model != null)
            {
                return _context.SaveChanges() > 0;
            }
            else
            {
                throw new Exception("当前记录不存在！");
            }
        }

        /// <summary>
        /// UpdateRecordRealOrderNo
        /// </summary>
        /// <param name="CardMerchant">修改对象</param>
        /// <returns></returns>
        private bool UpdateRecordRealOrderNo(long orderNo, long recordRealOrderNo, FlashPayContext flashPayContext = null)
        {
            var tableName = $"PaymentRecord_{DateTime.Now.ToString("MM")}";

            var month = GetOrderMonth(orderNo);
            if (month != DateTime.Now.ToString("MM"))
            {
                tableName = $"PaymentRecord_{month}";
            }

            var paymentRecord = this.GetPaymentRecord(orderNo);
            if (paymentRecord != null)
            {
                var sql = $"update {tableName} set RecordRealOrderNo={recordRealOrderNo} where  OrderNo={orderNo}";

                var updateStatusPaymentRecord = _context.Database.ExecuteSqlCommand(sql);
                if (updateStatusPaymentRecord <= 0)
                {
                    throw new Exception("数据库操作失败！");
                }
                return true;
            }
            else
            {
                throw new Exception("当前记录不存在！");
            }
        }

        /// <summary>
        /// 转成功
        /// </summary>
        /// <param name="reqeust">参数</param>
        /// <returns></returns>
        public JResult TurnSuccess(TurnReqeust reqeust)
        {
            var result = new JResult() {
                Success = false
            };

            System.Threading.Thread.Sleep(500);

            lock (_lock)
            {
                try
                {
                    var paymentRecordTableName = $"PaymentRecord_{DateTime.Now.ToString("MM")}";
                    var recordRealTableName = $"RecordReal_{DateTime.Now.ToString("MM")}";


                    var month = GetOrderMonth(reqeust.OrderNo);
                    if (month != DateTime.Now.ToString("MM"))
                    {
                        paymentRecordTableName = $"PaymentRecord_{month}";
                        recordRealTableName = $"RecordReal_{month}";
                    }

                    var paymentRecord = this.GetPaymentRecord(reqeust.OrderNo);
                    if (paymentRecord == null)
                    {
                        throw new Exception("订单记录不存在！");
                    }

                    var recordReal = this.Get(reqeust.RecordRealOrderNo);
                    if (recordReal != null)
                    {
                        //付款记录状态验证
                        if (paymentRecord.PaymentStatus != (sbyte)PaymentRecordPaymentStatus.付款中.GetHashCode())
                        {
                            throw new Exception("付款记录状态发生改变！");
                        }
                        //确认状态(自动审核通过、人工审核通过)
                        var confirmStatus = new List<int>()
                        {
                            (sbyte)PaymentRecordConfirmStatus.自动审核通过.GetHashCode(),
                            (sbyte)PaymentRecordConfirmStatus.人工审核通过.GetHashCode()
                        };
                        if (!confirmStatus.Contains(paymentRecord.ConfirmStatus))
                        {
                            throw new Exception("付款记录状态发生改变！");
                        }

                        //数据验证
                        if (recordReal.MatchOrderNo != null || recordReal.MatchOrderNo > 0)
                        {
                            throw new Exception("该实际支付记录已标记成功！");
                        }

                        var paymentRecordPaymentStatus = (sbyte)PaymentRecordPaymentStatus.付款成功.GetHashCode();

                        var sql = $"call sp_UpdateMatchPaymentRecord('{reqeust.OrderNo}', '{reqeust.RecordRealOrderNo}', '{paymentRecordPaymentStatus}');";

                        var connection = _context.Database.GetDbConnection();

                        using (var command = connection.CreateCommand())
                        {
                            command.CommandText = sql;
                            command.CommandType = CommandType.Text;
                            if (connection.State == ConnectionState.Closed)
                            {
                                connection.Open();
                            }

                            var updateSatatus = 0L;

                            using (var updateResult = command.ExecuteReader())
                            {
                                if (updateResult.Read())
                                {
                                    updateSatatus = updateResult.GetInt32(0);
                                }
                            }

                            if (updateSatatus <= 0) {
                                throw new Exception("更新付款RecordRealOrderNo失败！");
                            }
                        }

                        //日志
                        _logRecord.LogType = LogRecordLogType.Permission_Update.GetHashCode();
                        _logRecord.CreateName = reqeust.UserName;
                        _logRecord.LogLevel = (sbyte)LogLevel.Success.GetHashCode();
                        _logRecord.CreateDate = DateTime.Now;
                        _logRecord.LogRemark = $"付款记录转成功成功,付款订单编号：{reqeust.OrderNo},真实付款记录编号：{reqeust.RecordRealOrderNo}";
                        _logDao.Insert(_logRecord);

                        result.SuccessMessage = "操作成功！";
                        result.Success = true;
                        //tran.Commit();

                        try
                        {
                            this.Unusual(paymentRecord);
                        }
                        catch (Exception ex) {

                        }
                    }
                    else
                    {
                        _logRecord.LogType = LogRecordLogType.Permission_Update.GetHashCode();
                        _logRecord.CreateName = reqeust.UserName;
                        _logRecord.LogLevel = (sbyte)LogLevel.Failure.GetHashCode();
                        _logRecord.CreateDate = DateTime.Now;
                        _logRecord.LogRemark = $"真实付款记录不存在,付款订单编号：{reqeust.OrderNo},真实付款记录编号：{reqeust.RecordRealOrderNo}";
                        _logDao.Insert(_logRecord);

                        throw new Exception("真实付款记录不存在！");
                    }
                }
                catch (Exception ex)
                {
                    //tran.Rollback();
                    try
                    {
                        _logRecord.LogType = LogRecordLogType.Permission_Update.GetHashCode();
                        _logRecord.CreateName = reqeust.UserName;
                        _logRecord.LogLevel = (sbyte)LogLevel.Error.GetHashCode();
                        _logRecord.CreateDate = DateTime.Now;
                        _logRecord.LogRemark = $"操作失败,付款订单编号：{reqeust.OrderNo},真实付款记录编号：{reqeust.RecordRealOrderNo}";
                        _logDao.Insert(_logRecord);
                    }
                    catch
                    {
                    }

                    result.ErrorMessage = ex.Message;
                }
            }

            return result;
        }

        /// <summary>
        /// 转成功
        /// </summary>
        /// <param name="reqeust">参数</param>
        /// <returns></returns>
        public JResult EmptyRecordTurnSuccess(TurnReqeust reqeust)
        {
            var result = new JResult()
            {
                Success = false
            };

            System.Threading.Thread.Sleep(500);

            lock (_lock)
            {
                try
                {
                    var paymentRecordTableName = $"PaymentRecord_{DateTime.Now.ToString("MM")}";

                    var month = GetOrderMonth(reqeust.OrderNo);
                    if (month != DateTime.Now.ToString("MM"))
                    {
                        paymentRecordTableName = $"PaymentRecord_{month}";
                    }

                    var paymentRecord = this.GetPaymentRecord(reqeust.OrderNo);
                    if (paymentRecord == null)
                    {
                        throw new Exception("订单记录不存在！");
                    }

                    //付款记录状态验证
                    if (paymentRecord.PaymentStatus != (sbyte)PaymentRecordPaymentStatus.付款中.GetHashCode())
                    {
                        throw new Exception("付款记录状态发生改变！");
                    }
                    //确认状态(自动审核通过、人工审核通过)
                    var confirmStatus = new List<int>()
                    {
                        (sbyte)PaymentRecordConfirmStatus.自动审核通过.GetHashCode(),
                        (sbyte)PaymentRecordConfirmStatus.人工审核通过.GetHashCode()
                    };

                    if (!confirmStatus.Contains(paymentRecord.ConfirmStatus))
                    {
                        throw new Exception("付款记录状态发生改变！");
                    }

                    paymentRecord.PaymentStatus = (sbyte)PaymentRecordPaymentStatus.付款成功.GetHashCode();
                    paymentRecord.PaymentFailInfo = "人工确认成功";

                    var updatePaymentRecordSql = $"update {paymentRecordTableName} set PaymentStatus={paymentRecord.PaymentStatus},PaymentDate='{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}',PaymentFailInfo='{paymentRecord.PaymentFailInfo}' where  OrderNo={paymentRecord.OrderNo} and PaymentStatus={(sbyte)PaymentRecordPaymentStatus.付款中.GetHashCode()} and ConfirmStatus in({(sbyte)PaymentRecordConfirmStatus.自动审核通过},{(sbyte)PaymentRecordConfirmStatus.人工审核通过.GetHashCode()})";
                    var updateStatus = _context.Database.ExecuteSqlCommand(updatePaymentRecordSql);
                    if (updateStatus <= 0)
                    {
                        throw new Exception("操作失败！"); 
                    }
                    //日志
                    _logRecord.LogType = LogRecordLogType.PaymentRecord_TurnSuccess.GetHashCode();
                    _logRecord.CreateName = reqeust.UserName;
                    _logRecord.LogLevel = (sbyte)LogLevel.Success.GetHashCode();
                    _logRecord.CreateDate = DateTime.Now;
                    _logRecord.LogRemark = $"付款记录转成功成功,付款订单编号：{reqeust.OrderNo},真实付款记录编号：{reqeust.RecordRealOrderNo}";
                    _logDao.Insert(_logRecord);

                    result.SuccessMessage = "操作成功！";
                    result.Success = true;
                }
                catch (Exception ex)
                {
                    try
                    {
                        _logRecord.LogType = LogRecordLogType.PaymentRecord_TurnSuccess.GetHashCode();
                        _logRecord.CreateName = reqeust.UserName;
                        _logRecord.LogLevel = (sbyte)LogLevel.Error.GetHashCode();
                        _logRecord.CreateDate = DateTime.Now;
                        _logRecord.LogRemark = $"操作失败,付款订单编号：{reqeust.OrderNo},真实付款记录编号：{reqeust.RecordRealOrderNo}";
                        _logDao.Insert(_logRecord);
                    }
                    catch
                    {
                    }

                    result.ErrorMessage = ex.Message;
                }
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="input"></param>
        /// <param name="places"></param>
        /// <returns></returns>
        private double RoundUp(double input, int places)
        {
            double multiplier = Math.Pow(10, Convert.ToDouble(places));
            return Math.Ceiling(input * multiplier) / multiplier;
        }

        /// <summary>
        /// (FlashPay)转成功
        /// </summary>
        /// <param name="reqeust">参数</param>
        /// <returns></returns>
        public JResult FlashPayTurnSuccess(TurnReqeust reqeust)
        {
            var result = new JResult()
            {
                Success = false
            };

            System.Threading.Thread.Sleep(500);

            lock (_lock)
            {
                try
                {
                    var paymentRecordTableName = $"PaymentRecord_{DateTime.Now.ToString("MM")}";

                    var month = GetOrderMonth(reqeust.OrderNo);
                    if (month != DateTime.Now.ToString("MM"))
                    {
                        paymentRecordTableName = $"PaymentRecord_{month}";
                    }

                    var paymentRecord = this.GetPaymentRecord(reqeust.OrderNo);
                    if (paymentRecord == null)
                    {
                        throw new Exception("订单记录不存在！");
                    }

                    //付款记录状态验证
                    if (paymentRecord.PaymentStatus != (sbyte)PaymentRecordPaymentStatus.付款中.GetHashCode())
                    {
                        throw new Exception("付款记录状态发生改变！");
                    }
                    //确认状态(自动审核通过、人工审核通过)
                    var confirmStatus = new List<int>()
                    {
                        (sbyte)PaymentRecordConfirmStatus.自动审核通过.GetHashCode(),
                        (sbyte)PaymentRecordConfirmStatus.人工审核通过.GetHashCode()
                    };

                    if (!confirmStatus.Contains(paymentRecord.ConfirmStatus))
                    {
                        throw new Exception("付款记录状态发生改变！");
                    }

                    paymentRecord.PaymentStatus = (sbyte)PaymentRecordPaymentStatus.付款成功.GetHashCode();
                    paymentRecord.PaymentFailInfo = "人工确认成功";

                    //获取银行卡
                    var bankCard = _context.BankCard.Where(c => c.CardType == (sbyte)CardType.付款卡 && c.PaymentType == (sbyte)PaymentInterfacePaymentType.FlashPay).Select(c => new {
                        c.Bcid,
                        c.OrderNo,
                        c.CardName,
                        c.CardNumber,
                        c.CardType,
                        c.PaymentType,
                        c.PayFeeRatio,
                        c.CompanyId
                    }).FirstOrDefault();

                    //汇率
                    var feeTotal = new decimal(0);

                    if (bankCard != null)
                    {
                        feeTotal = (Math.Ceiling(bankCard.PayFeeRatio * paymentRecord.WithdrawalAmount * 100))/100;
                    }
                    else
                    {
                        throw new Exception("该订单的付款卡不存在！");
                    }

                    if (feeTotal.Equals(0))
                    {
                        var company = _context.Company.FirstOrDefault(c => c.CompanyId == bankCard.CompanyId);
                        if (company != null && company.PayRate.HasValue)
                        {
                            feeTotal = company.PayRate.Value * paymentRecord.WithdrawalAmount;
                        }
                    }

                    var updatePaymentRecordSql = $"update {paymentRecordTableName} set PaymentStatus={paymentRecord.PaymentStatus},PaymentDate='{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}',PaymentFailInfo='{paymentRecord.PaymentFailInfo}',ReadDate=null,FeeTotal={feeTotal},CardNumber='{bankCard.CardNumber}',PaymentCardId={bankCard.Bcid},WithdrawalFee={feeTotal} where OrderNo={paymentRecord.OrderNo} and PaymentStatus={(sbyte)PaymentRecordPaymentStatus.付款中.GetHashCode()} and NoticeStatus={(sbyte)PaymentRecordNoticeStatus.未通知} and NoticeTimes=0 and ConfirmStatus in({(sbyte)PaymentRecordConfirmStatus.自动审核通过},{(sbyte)PaymentRecordConfirmStatus.人工审核通过.GetHashCode()}) and RecordRealOrderNo is null";
                    var updateStatus = _context.Database.ExecuteSqlCommand(updatePaymentRecordSql);
                    if (updateStatus <= 0)
                    {
                        throw new Exception("操作失败！");
                    }
                    //日志
                    _logRecord.LogType = LogRecordLogType.PaymentRecord_TurnSuccess.GetHashCode();
                    _logRecord.CreateName = reqeust.UserName;
                    _logRecord.LogLevel = (sbyte)LogLevel.Success.GetHashCode();
                    _logRecord.CreateDate = DateTime.Now;
                    _logRecord.LogRemark = $"付款记录转成功成功,付款订单编号：{reqeust.OrderNo},真实付款记录编号：{reqeust.RecordRealOrderNo}";
                    _logDao.Insert(_logRecord);

                    result.SuccessMessage = "操作成功！";
                    result.Success = true;
                }
                catch (Exception ex)
                {
                    //tran.Rollback();
                    try
                    {
                        _logRecord.LogType = LogRecordLogType.PaymentRecord_TurnSuccess.GetHashCode();
                        _logRecord.CreateName = reqeust.UserName;
                        _logRecord.LogLevel = (sbyte)LogLevel.Error.GetHashCode();
                        _logRecord.CreateDate = DateTime.Now;
                        _logRecord.LogRemark = $"操作失败,付款订单编号：{reqeust.OrderNo},真实付款记录编号：{reqeust.RecordRealOrderNo}";
                        _logDao.Insert(_logRecord);
                    }
                    catch
                    {
                    }

                    result.ErrorMessage = ex.Message;
                }
            }

            return result;
        }

        /// <summary>
        /// (TF)转成功
        /// </summary>
        /// <param name="reqeust">参数</param>
        /// <returns></returns>
        public JResult TFTurnSuccess(TurnReqeust reqeust)
        {
            var result = new JResult()
            {
                Success = false
            };

            System.Threading.Thread.Sleep(500);

            lock (_lock)
            {
                try
                {
                    var paymentRecordTableName = $"PaymentRecord_{DateTime.Now.ToString("MM")}";

                    var month = GetOrderMonth(reqeust.OrderNo);
                    if (month != DateTime.Now.ToString("MM"))
                    {
                        paymentRecordTableName = $"PaymentRecord_{month}";
                    }

                    var paymentRecord = this.GetPaymentRecord(reqeust.OrderNo);
                    if (paymentRecord == null)
                    {
                        throw new Exception("订单记录不存在！");
                    }

                    //付款记录状态验证
                    if (paymentRecord.PaymentStatus != (sbyte)PaymentRecordPaymentStatus.付款中.GetHashCode())
                    {
                        throw new Exception("付款记录状态发生改变！");
                    }
                    //确认状态(自动审核通过、人工审核通过)
                    var confirmStatus = new List<int>()
                    {
                        (sbyte)PaymentRecordConfirmStatus.自动审核通过.GetHashCode(),
                        (sbyte)PaymentRecordConfirmStatus.人工审核通过.GetHashCode()
                    };

                    if (!confirmStatus.Contains(paymentRecord.ConfirmStatus))
                    {
                        throw new Exception("付款记录状态发生改变！");
                    }

                    paymentRecord.PaymentStatus = (sbyte)PaymentRecordPaymentStatus.付款成功.GetHashCode();
                    paymentRecord.PaymentFailInfo = "人工确认成功";

                    //获取银行卡
                    var bankCard = _context.BankCard.Where(c => c.CardType == (sbyte)CardType.付款卡 && c.PaymentType == (sbyte)PaymentInterfacePaymentType.通付).Select(c => new {
                        c.Bcid,
                        c.OrderNo,
                        c.CardName,
                        c.CardNumber,
                        c.CardType,
                        c.PaymentType,
                        c.PayFeeRatio,
                        c.CompanyId
                    }).FirstOrDefault();

                    //汇率
                    var feeTotal = new decimal(0);

                    if (bankCard != null)
                    {
                        feeTotal = bankCard.PayFeeRatio * paymentRecord.WithdrawalAmount;
                    }
                    else
                    {
                        throw new Exception("该订单的付款卡不存在！");
                    }

                    if (feeTotal.Equals(0))
                    {
                        var company = _context.Company.FirstOrDefault(c => c.CompanyId == bankCard.CompanyId);
                        if (company != null && company.PayRate.HasValue)
                        {
                            feeTotal = company.PayRate.Value * paymentRecord.WithdrawalAmount;
                        }
                    }

                    var updatePaymentRecordSql = $"update {paymentRecordTableName} set PaymentStatus={paymentRecord.PaymentStatus},PaymentDate='{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}',PaymentFailInfo='{paymentRecord.PaymentFailInfo}',ReadDate=null,FeeTotal={feeTotal},CardNumber='{bankCard.CardNumber}',PaymentCardId={bankCard.Bcid},WithdrawalFee=2 where  OrderNo={paymentRecord.OrderNo} and PaymentStatus={(sbyte)PaymentRecordPaymentStatus.付款中.GetHashCode()} and NoticeStatus={(sbyte)PaymentRecordNoticeStatus.未通知} and NoticeTimes=0 and ConfirmStatus in({(sbyte)PaymentRecordConfirmStatus.自动审核通过},{(sbyte)PaymentRecordConfirmStatus.人工审核通过.GetHashCode()}) and RecordRealOrderNo is null";
                    var updateStatus = _context.Database.ExecuteSqlCommand(updatePaymentRecordSql);
                    if (updateStatus <= 0)
                    {
                        throw new Exception("操作失败！");
                    }
                    //日志
                    _logRecord.LogType = LogRecordLogType.PaymentRecord_TurnSuccess.GetHashCode();
                    _logRecord.CreateName = reqeust.UserName;
                    _logRecord.LogLevel = (sbyte)LogLevel.Success.GetHashCode();
                    _logRecord.CreateDate = DateTime.Now;
                    _logRecord.LogRemark = $"付款记录转成功成功,付款订单编号：{reqeust.OrderNo},真实付款记录编号：{reqeust.RecordRealOrderNo}";
                    _logDao.Insert(_logRecord);

                    result.SuccessMessage = "操作成功！";
                    result.Success = true;
                }
                catch (Exception ex)
                {
                    //tran.Rollback();
                    try
                    {
                        _logRecord.LogType = LogRecordLogType.PaymentRecord_TurnSuccess.GetHashCode();
                        _logRecord.CreateName = reqeust.UserName;
                        _logRecord.LogLevel = (sbyte)LogLevel.Error.GetHashCode();
                        _logRecord.CreateDate = DateTime.Now;
                        _logRecord.LogRemark = $"操作失败,付款订单编号：{reqeust.OrderNo},真实付款记录编号：{reqeust.RecordRealOrderNo}";
                        _logDao.Insert(_logRecord);
                    }
                    catch
                    {
                    }

                    result.ErrorMessage = ex.Message;
                }
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="paymentRecord"></param>
        private void Unusual(PaymentRecord paymentRecord)
        {
            /**
             * 「转成功」后要去多做一件事情：
             *  1. 修复馀额变化记录上的「疑似异常」
             *  2. 修复银行卡上面馀额的红色警告
             *  3. 并且将该笔转成功的订单号，显示在对应的「馀额变化记录」中。
             */
            var tableName = $"AdjustBalance_{DateTime.Now.ToString("MM")}";

            var month = GetOrderMonth(paymentRecord.OrderNo);

            if (month != DateTime.Now.ToString("MM"))
            {
                tableName = $"AdjustBalance_{month}";
            }

            var sql = $"SELECT * FROM {tableName} WHERE AdjustStatus=2 and CreateRemark = '疑似异常' and OrderNo is null and CardNumber='{paymentRecord.CardNumber}' and Amount={paymentRecord.WithdrawalAmount} and (CreateDate >= '{paymentRecord.PaymentDate.Value.ToString("yyyy-MM-dd HH:mm:ss")}' AND CreateDate<='{paymentRecord.PaymentDate.Value.AddMinutes(10).ToString("yyyy-MM-dd HH:mm:ss")}') ORDER BY CreateDate ASC  LIMIT 1";

            var adjustBalance = _context.AdjustBalance
                .FromSql(sql)
                .AsNoTracking()
                .SingleOrDefault();

            if (adjustBalance != null)
            {
                /**
                 * 1.先去跟该银行卡的 AdjustBalanceRID 做比对，如果一样的话，才清空(null)。
                 * 2.然后最后还要把 AdjustBalance 的 CreateRemark 上面的「疑似异常」清空(null)，并切压上当初那笔 OrderNo
                 */

                using (var tran = _context.Database.BeginTransaction())
                {
                    try
                    {
                        var bankCard = _context.BankCard.FirstOrDefault(p => p.Bcid == adjustBalance.CardBcid);
                        if (bankCard == null || bankCard.AdjustBalanceRid != adjustBalance.Rid)
                        {
                            return;
                        }

                        bankCard.AdjustBalanceRid = null;
                        _context.Entry<BankCard>(bankCard);
                        _context.SaveChanges();


                        var tableNameAdjustBalance = $"AdjustBalance_{DateTime.Now.ToString("MM")}";

                        var monthAdjustBalance = GetOrderMonth(adjustBalance.Rid);

                        if (monthAdjustBalance != DateTime.Now.ToString("MM"))
                        {
                            tableNameAdjustBalance = $"AdjustBalance_{month}";
                        }

                        var updateAdjustBalanceSql = $"update {tableNameAdjustBalance} set CreateRemark=null,OrderNo={paymentRecord.OrderNo} where RID={adjustBalance.Rid}";

                        var updateStatusAdjustBalance = _context.Database.ExecuteSqlCommand(updateAdjustBalanceSql);
                        if (updateStatusAdjustBalance <= 0)
                        {
                            throw new Exception("数据库操作失败！");
                        }

                        tran.Commit();
                    }
                    catch (Exception ex)
                    {
                        tran.Rollback();
                    }

                }
            }
        }

        /// <summary>
        /// 转失败
        /// </summary>
        /// <param name="reqeust">参数</param>
        /// <returns></returns>
        public JResult TurnFailure(TurnReqeust reqeust)
        {
            var result = new JResult()
            {
                Success = false
            };

            System.Threading.Thread.Sleep(500);

            lock (_lock)
            {
                using (var tran = _context.Database.BeginTransaction())
                {
                    try
                    {
                        var paymentRecordTableName = $"PaymentRecord_{DateTime.Now.ToString("MM")}";

                        var month = GetOrderMonth(reqeust.OrderNo);
                        if (month != DateTime.Now.ToString("MM"))
                        {
                            paymentRecordTableName = $"PaymentRecord_{month}";
                        }

                        var paymentRecord = this.GetPaymentRecord(reqeust.OrderNo);
                        if (paymentRecord == null)
                        {
                            throw new Exception("订单记录不存在！");
                        }

                        //状态验证
                        if (paymentRecord.PaymentStatus != (sbyte)PaymentRecordPaymentStatus.付款中.GetHashCode())
                        {
                            throw new Exception("只有付款单为付款状态为付款中时才能转失败！");
                        }

                        if (paymentRecord.NoticeStatus != (sbyte)PaymentRecordNoticeStatus.未通知.GetHashCode())
                        {
                            throw new Exception("只有付款单通知状态为未通知时才能转失败！");
                        }

                        paymentRecord.PaymentStatus = (sbyte)PaymentRecordPaymentStatus.付款失败.GetHashCode();
                        paymentRecord.NoticeStatus = (sbyte)PaymentRecordNoticeStatus.通知失败.GetHashCode();
                        paymentRecord.NoticeTimes = 1;
                        paymentRecord.NoticeLastDate = DateTime.Now;
                        paymentRecord.PaymentFailInfo = "人工确认失败";
                        paymentRecord.PaymentDate = DateTime.Now;

                        var updateSql = $"update {paymentRecordTableName} set PaymentStatus={paymentRecord.PaymentStatus},NoticeStatus={paymentRecord.NoticeStatus},NoticeTimes={paymentRecord.NoticeTimes},NoticeLastDate='{paymentRecord.NoticeLastDate.Value.ToString("yyyy-MM-dd HH:mm:ss")}',PaymentFailInfo='{paymentRecord.PaymentFailInfo}',PaymentDate='{paymentRecord.PaymentDate.Value.ToString("yyyy-MM-dd HH:mm:ss")}' where  OrderNo={reqeust.OrderNo} and PaymentStatus={(sbyte)PaymentRecordPaymentStatus.付款中.GetHashCode()} and NoticeStatus={(sbyte)PaymentRecordNoticeStatus.未通知.GetHashCode()}";
                        var updateStatusPaymentRecord = _context.Database.ExecuteSqlCommand(updateSql);
                        if (updateStatusPaymentRecord <= 0) {
                            throw new Exception("操作失败！");
                        }

                        //日志
                        _logRecord.Ip = reqeust.Ip;
                        _logRecord.LogType = LogRecordLogType.Permission_Update.GetHashCode();
                        _logRecord.CreateName = reqeust.UserName;
                        _logRecord.LogLevel = (sbyte)LogLevel.Success.GetHashCode();
                        _logRecord.CreateDate = DateTime.Now;
                        _logRecord.LogRemark = $"付款记录转失败成功,付款订单编号：{reqeust.OrderNo},真实付款记录编号：{reqeust.RecordRealOrderNo}";
                        _logDao.Insert(_logRecord);


                        result.SuccessMessage = "操作成功！";
                        result.Success = true;
                        tran.Commit();
                    }
                    catch (Exception ex)
                    {
                        tran.Rollback();
                        try
                        {
                            _logRecord.Ip = reqeust.Ip;
                            _logRecord.LogType = LogRecordLogType.Permission_Update.GetHashCode();
                            _logRecord.CreateName = reqeust.UserName;
                            _logRecord.LogLevel = (sbyte)LogLevel.Error.GetHashCode();
                            _logRecord.CreateDate = DateTime.Now;
                            _logRecord.LogRemark = $"付款记录转失败失败,付款订单编号：{reqeust.OrderNo},真实付款记录编号：{reqeust.RecordRealOrderNo}";
                            _logDao.Insert(_logRecord);
                        }
                        catch
                        {
                        }
                        result.ErrorMessage = ex.Message;
                    }
                }
            }

            return result;
        }

        /// <summary>
        /// 获取所有记录
        /// </summary>
        /// <param name="query">查询条件</param>
        /// <returns>List<UserInfo></returns>
        public List<RecordReal> GetList(RecordRealQuery query)
        {
            //多条件查询
            var where = PredicateBuilder.True<RecordReal>();

            var list = _context.RecordReal.Where(where.Compile()).ToList();

            return list;
        }

        /// <summary>
        /// 获取银行卡前四位和后四位
        /// </summary>
        /// <param name="bankCardNumber"></param>
        /// <returns></returns>
        private string GetBankCardNumber(string bankCardNumber)
        {
            if (string.IsNullOrEmpty(bankCardNumber)){
                return "";
            }else {
                if (bankCardNumber.Length >= 8) {
                    return bankCardNumber.Substring(0, 4) + bankCardNumber.Substring(bankCardNumber.Length - 4);
                }
                else {
                    return "";
                }
            }
        }

        /// <summary>
        /// 获取付款记录的真实付款记录
        /// </summary>
        /// <returns></returns>
        public PaymentRecordRealResult<List<PaymentRecordRealResponse>> GetPaymentRecordReals(PaymentRecordRealQuery query) {

            var result = new PaymentRecordRealResult<List<PaymentRecordRealResponse>>() {
                Success = true,
                Minutes = query.PlatformType.Equals(PlatformType.B2B.GetHashCode())? 1: 3
            };

            //农业 工商 青岛 10分钟

            if (query.UserPermission.Contains("PaymentRecord0010")) {
                result.StatusCode = "PaymentRecord0010";
            }

            var paymentRecordTableName = $"PaymentRecord_{DateTime.Now.ToString("MM")}";
            var recordRealTableName = $"RecordReal_{DateTime.Now.ToString("MM")}";


            var month = GetOrderMonth(query.OrderNo);
            if (month != DateTime.Now.ToString("MM"))
            {
                _context.ReloadModelCreating(month);

                paymentRecordTableName = $"PaymentRecord_{month}";
                recordRealTableName = $"RecordReal_{month}";
            }


            var sql = $"SELECT * FROM {paymentRecordTableName} WHERE OrderNo={query.OrderNo} and RecordRealOrderNo is NULL";
            var paymentRecord = _context.PaymentRecord
                .FromSql(sql)
                .AsNoTracking()
                .SingleOrDefault();

            if (paymentRecord != null)
            {
                if (paymentRecord.ReadDate.HasValue)
                {
                    var ts = DateTime.Now.Subtract(paymentRecord.ReadDate.Value).TotalMinutes;
                    if (ts > 0)
                    {
                        result.PaymentDateTimeDifference = ts;
                    }
                }

                if (!paymentRecord.ReadDate.HasValue)
                {
                    throw new Exception("ReadDate为空");
                }



                var readDateAddMinutes = paymentRecord.ReadDate.Value.AddMinutes(query.Minutes);
                if (!paymentRecord.PaymentCardId.HasValue)
                {
                    throw new Exception("未设置付款银行");
                }
                var recordRealSql = $"SELECT * FROM {recordRealTableName} WHERE MatchOrderNo is NULL and OperatingDate>'{paymentRecord.CreateDbdate.ToString("yyyy-MM-dd HH:mm:ss")}' and OperatingDate<='{readDateAddMinutes.ToString("yyyy-MM-dd HH:mm:ss")}' and CardBcid={paymentRecord.PaymentCardId} and Amount={paymentRecord.WithdrawalAmount} and ClientAccountName='{paymentRecord.WithdrawalAccountName}' and CompanyId={paymentRecord.CompanyId} and ClientCardNumber='{paymentRecord.WithdrawalCardNumber}'";
                var recordReal = _context.RecordReal
                    .FromSql(recordRealSql)
                    .AsNoTracking()
                    .ToList();

                var paymentRecordRealResponses = new List<PaymentRecordRealResponse>();

                var companys = _context.Company.ToList();
                var bankCards = _context.BankCard.ToList();

                if (query.PlatformType.Equals(PlatformType.B2B.GetHashCode())) {
                    var bank = bankCards.FirstOrDefault(c => c.Bcid == paymentRecord.PaymentCardId);
                    if (bank != null && (bank.BankName.Contains("农业") || bank.BankName.Contains("工商") || bank.BankName.Contains("青岛")) && paymentRecord.WithdrawalAmount>5000) {
                        result.Minutes = 10;
                    }
                }

                foreach (var item in recordReal)
                {

                    var companyName = "";
                    var company = companys.FirstOrDefault(c => c.CompanyId == item.CompanyId);
                    if (company != null)
                    {
                        companyName = company.CompanyName;
                    }

                    var bankName = "";
                    var bankCard = bankCards.FirstOrDefault(c => c.Bcid == item.CardBcid);
                    if (bankCard != null)
                    {
                        bankName = bankCard.BankName;
                    }

                    var paymentRecordRealResponse = new PaymentRecordRealResponse();
                    paymentRecordRealResponse.OrderNo = item.OrderNo.ToString();
                    paymentRecordRealResponse.AfterBalance = item.AfterBalance.ToString("#0.00");
                    paymentRecordRealResponse.CompanyId = item.CompanyId;
                    paymentRecordRealResponse.CompanyName = companyName;

                    paymentRecordRealResponse.OperatingDate = item.OperatingDate.ToString("yyyy-MM-dd HH:mm:ss");
                    paymentRecordRealResponse.CardBcid = item.CardBcid;
                    paymentRecordRealResponse.CardBankName = bankName;
                    paymentRecordRealResponse.Amount = item.Amount.ToString("#0.00");
                    paymentRecordRealResponse.ClientBankName = item.ClientBankName;
                    paymentRecordRealResponse.ClientAccountName = item.ClientAccountName;
                    paymentRecordRealResponse.ClientCardNumber = GetBankCardNumber(item.ClientCardNumber);
                    paymentRecordRealResponse.PlatformType = (sbyte)query.PlatformType;
                    paymentRecordRealResponses.Add(paymentRecordRealResponse);
                }

                result.Data = paymentRecordRealResponses;
                return result;
            }
            else {
                return null;
            }
        }

        /// <summary>
        /// 已实际付款记录(未入账收款记录)
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public DataGrid<RecordRealResponse> GetPaymentRecordPager(RecordRealQuery query)
        {
            var companyIds = string.Join(", ", query.CompanyIds);

            var sql = $"call sp_SelectRecordReal('{query.StartTime}', '{query.EndTime}', '{companyIds}','{query.RecordType}');";
            var q = _context.RecordReal.FromSql(sql);

            #region 模型转换
            var companys = _context.Company.ToList();
            var bankCards = _context.BankCard.ToList();


            //公司名称
            if (!string.IsNullOrEmpty(query.CompanyName))
            {
                var comSearch = companys.Where(p => p.CompanyName.Contains(query.CompanyName)).ToList();
                q = q.Where(c => comSearch.Select(p => p.CompanyId).Contains(c.CompanyId));
            }

            //收付款卡用户名
            if (!string.IsNullOrEmpty(query.CardName))
            {
                var cardSearch = bankCards.Where(p => p.CardName.Contains(query.CardName)).ToList();
                if (cardSearch != null && cardSearch.Any())
                {
                    q = q.Where(c => cardSearch.Select(p => p.Bcid).Contains(c.CardBcid));
                }
                else
                {
                    q = q.Where(c => c.CardBcid==-1);
                }
            }

            //收款金额
            if (query.StartAmount>0)
            {
                q = q.Where(c => c.Amount>= query.StartAmount);
            }
            if (query.EndAmount > 0)
            {
                q = q.Where(c => c.Amount <= query.EndAmount);
            }

            //客户姓名
            if (!string.IsNullOrEmpty(query.ClientAccountName))
            {
                q = q.Where(c => c.ClientAccountName.Contains(query.ClientAccountName));
            }
            var list = q.Skip((query.Page.Value - 1) * query.Rows.Value).Take(query.Rows.Value).OrderByDescending(p => p.OperatingDate).ToList();
            var recordRealResponses = new List<RecordRealResponse>();

            list.ForEach(item =>
            {
                var depositOrPaymentRecordResponse = new RecordRealResponse();

                #region 公司
                var companyName = "";
                var companyNameEn = "";
                if (companys != null && companys.Any())
                {
                    var company = companys.FirstOrDefault(p => p.CompanyId == item.CompanyId);
                    if (company != null)
                    {
                        companyName = company.CompanyName;
                        companyNameEn = company.CompanyNameEn;
                    }
                }
                #endregion

                #region 银行卡
                var bankName = "";
                var cardNumber = "";
                var cardName = "";
                if (bankCards != null && bankCards.Any())
                {
                    var bankCard = bankCards.FirstOrDefault(p => p.Bcid == item.CardBcid);
                    if (bankCard != null)
                    {
                        bankName = bankCard.BankName;
                        cardNumber = bankCard.CardNumber;
                        cardName = bankCard.CardName;
                    }
                }
                #endregion

                depositOrPaymentRecordResponse.OrderNo = item.OrderNo.ToString();
                depositOrPaymentRecordResponse.ClientOrderNo = item.ClientOrderNo;
                depositOrPaymentRecordResponse.AfterBalance = item.AfterBalance.ToString("#0.00");
                depositOrPaymentRecordResponse.CompanyName = companyName;
                depositOrPaymentRecordResponse.CompanyNameEn = companyNameEn;
                depositOrPaymentRecordResponse.BankName = bankName;
                depositOrPaymentRecordResponse.CardName = cardName;
                depositOrPaymentRecordResponse.CardNumber = Util.WebUtil.SetCardNumber(cardNumber);
                depositOrPaymentRecordResponse.Amount = item.Amount.ToString("#0.00");
                depositOrPaymentRecordResponse.OperatingDate = item.OperatingDate;
                depositOrPaymentRecordResponse.ClientBankName = item.ClientBankName;
                depositOrPaymentRecordResponse.ClientAccountName = item.ClientAccountName;
                depositOrPaymentRecordResponse.ClientCardNumber = item.ClientCardNumber;
                depositOrPaymentRecordResponse.MatchOrderNo = item.MatchOrderNo.HasValue ? item.MatchOrderNo.Value.ToString():null;
                depositOrPaymentRecordResponse.VmClientID = item.VmClientId;
                depositOrPaymentRecordResponse.Remark = item.Remark;

                recordRealResponses.Add(depositOrPaymentRecordResponse);
            });
            #endregion

            return new DataGrid<RecordRealResponse>()
            {
                Total = q.Count(),
                Rows = recordRealResponses,
                Success = true
            };
        }
    }
}
